<?php

/**
 * Created by PhpStorm.
 * User: thorjiang
 * Date: 2018/5/9
 * Time: 18:32
 */

namespace App\Http\Services;

use App\Models\AppConfigModel;
use Illuminate\Support\Facades\Redis;
use DB;

/**
 * 缓存服务
 * Class CacheService
 * @package App\Http\Services
 */
class CacheService
{
    // 获取多个 app:keys
    public static function getAppKeys($keys)
    {
        if (!count($keys)) {
            return false;
        }

        $key = 'app:keys';
        if (Redis::hExists($key, $keys[0])) {
            $data = Redis::hmget($key, $keys);
        } else {
            $data = AppConfigModel::all()->toArray();
            $data = array_combine(array_column($data, 'key'), array_column($data, 'value'));
            Redis::hmset($key, $data);
            $data = Redis::hmget($key, $keys);
        }

        return $data;
    }

    public static function setUserToken($user_id, $token)
    {
        if (Redis::exists('token:user:'. $user_id)) {
            Redis::del('token:user:'. $user_id, 'user:token:'. Redis::get('token:user:'. $user_id));
        }

//        $ttl = '15552000'; // 3600*24*180
        Redis::set('user:token:'. $token, $user_id);
        Redis::set('token:user:'. $user_id, $token);
    }

    public static function getUserToken($token)
    {
        if (Redis::exists('user:token:'. $token)) {
            return Redis::get('user:token:'. $token);
        }

        return false;
    }

    /**
     * 获取用户信息
     * @param $userId
     * @param null $field
     * @return array|bool|mixed
     */
    public static function getUserInfo($userId, $field = null)
    {
        $key = 'user:'. $userId;
        if (Redis::exists($key)) {
            if ($field) {
                if (is_array($field)) {
                    return Redis::hMGet($key, $field);
                } else {
                    return Redis::hGet($key, $field);
                }
            } else {
                return Redis::hGetAll($key);
            }
        } else {
            $row = DB::select('select * from `user` where id = :id', ['id' => $userId]);

            $row = (array) $row;
            if (!$row) {
                return false;
            }

            Redis::hMset($key, $row);
            Redis::expire($key, 3600);
            if ($field) {
                if (is_array($field)) {
                    foreach ($field as $key) {
                        $items[] = $row[$key];
                    }
                    return $items;
                } else {
                    return $row[$field];
                }
            } else {
                return $row;
            }
        }
    }




    public static function getRoomUserCount($roomId)
    {
        $number = (int) Redis::get('members:num:' . $roomId);

        if ($number == 0) {
            return 1;
        }

        return $number;
    }

    public static function multiGetRoomUserCnt($roomIds)
    {
        $keys = [];
        foreach ($roomIds as $roomId) {
            $keys[] = 'members:num:' . $roomId;
        }
        return Redis::mget($keys);
    }

    public static function getRoomInfo($roomId)
    {
        if (Redis::exists('room:info:'. $roomId)) {
            $room = Redis::hGetAll('room:info:'. $roomId);
        } else {
            $room = DbClient::findRow('SELECT * FROM room WHERE id = ?', [$roomId]);
            Redis::hMset('room:info:'. $roomId, $room);
        }

        return $room;
    }

    public static function getRoomUser($roomId)
    {
        return Redis::lrange('members:' . $roomId, 0, 2);
        //return join(',', [1, 2, 3]);
    }

    // 房间中正在游戏的用户
    public static function getRoomPlayer($roomId)
    {
        return Redis::hGet('game:room', $roomId);
    }

    public static function getUserZone($userId)
    {
        if (Redis::hExists('user:zone', $userId)) {
            return Redis::hGet('user:zone', $userId);
        }
        return false;
    }

    // 存储用户的换区历史, 在可选大区中进行调度
    public static function changeUserZone($userId, $zoneId = 0)
    {
        if (empty($zoneId)) {
            $zoneId = static::dispatchZoneByUser($userId);
        }

        return static::roomServerDispatch($userId, $zoneId);
    }

    // 通过code获取用户信息
    public static function getUserDataByInviteCode($key)
    {
        $data = Redis::hGetAll('user:invite:code:' . $key);
        if (!$data) {
            $data = User::getUserDataByInviteCode($key);
            if (empty($data)) {
                // 从meta 表里再读一次
                $data = UserMeta::getUserIdByCode($key);
                if (empty($data)) {
                    return [];
                }
            }
            //$data = array_combine(array_column($data, 'id'), array_column($data, 'nickname'));
            Redis::hMset('user:invite:code:' . $key, $data);
            //$data = Redis::hGetAll('user:invite_code:' . $key);
        }

        return $data;
    }

    public static function getPhyZoneByVirtualZone($zoneId)
    {
        $zone = self::getZoneInfo($zoneId);
        $splits = explode('/', $zone['room_etcd_path']);

        return array_pop($splits);
    }

    //判断两个虚拟区是否在一个物理区
    public static function checkVirtualZoneLocation($zoneId1, $zoneId2)
    {
        $zone1 = self::getZoneInfo($zoneId1);
        $zone2 = self::getZoneInfo($zoneId2);

        $splits = explode('/',$zone1['room_etcd_path']);
        $phyId1 = array_pop($splits);

        $splits = explode('/',$zone2['room_etcd_path']);
        $phyId2 = array_pop($splits);

        return $phyId1 == $phyId2 ? 1 : 0;
    }

    public static function getRoomIdsByTag($tagId)
    {
        $roomIds = Redis::sMembers('tag:roomlist:'.$tagId);
        if (empty($roomIds)) {
            $roomIds = DbClient::findAll('SELECT room_id FROM room_tag WHERE tag_id = ? AND status = ?', [$tagId, RoomTag::DB_STATUS['normal']]);

            $roomIds = array_column($roomIds, 'room_id');

            Redis::sAdd('tag:roomlist:'. $tagId, ...$roomIds);
        }

        return $roomIds;
    }

    public static function getTags($types=[Tag::TYPE['brand'], Tag::TYPE['topic']])
    {
        $key = 'tag:list';
        $tags = Redis::get($key);
        if (empty($tags)) {
            $tags = DbClient::findAll('SELECT tag_id, `name`, zone_id, `type`, is_admin_only, img, introduction, desc_url, priority FROM tag WHERE status = '.Tag::DB_STATUS['normal'].' ORDER BY priority DESC');
            Redis::set($key, json_encode($tags));
        } else {
            $tags = json_decode($tags, true);
        }

        $ret = [];
        foreach ($tags as $tag) {
            if (in_array($tag['type'], $types)) {
                $ret[] = $tag;
            }
        }

        return $ret;
    }

    public static function getTagInfo($tagId)
    {
        $tags = self::getTags();

        foreach ($tags as $tag) {
            if ($tag['tag_id'] == $tagId) {
                return $tag;
            }
        }

        return [];
    }

    public static function getLastGameBp($uid)
    {
        $key = 'game:bp:last:'.$uid;
        $keytemp = 'game:bp:last:temp:'.$uid;
        $bp = Redis::get($keytemp);
        if ($bp == null) {
            $bp = Redis::get($key);
            if ($bp == null) {
                $bp = DbClient::findColumn('SELECT credits FROM bp_inner_order WHERE user_id=? and type="game" and category="recharge" and state="succeed" ORDER BY id desc limit 1', [$uid]);
                $bp = $bp ?: 0;
                Redis::set($key, $bp);
            }
        }
        return $bp;
    }

    public static function getDailyHaveBp($uid)
    {
        $key = 'daily:bp:'.$uid;
        $bp = Redis::get($key);
        if (empty($bp)) {
            return "";
        }
        return $bp;
    }

    public static function setDailyHaveBp($uid,$bp)
    {
        $key = 'daily:bp:'.$uid;
        $t = time();
        $end = mktime(23,59,59,date("m",$t),date("d",$t),date("Y",$t));
        $ttl =$end-$t;
        $bp = Redis::setex($key,$ttl,$bp);
        if (empty($bp)) {
            return "";
        }
        return "1";
    }

    public static function setLastGameBp($uid,$r)
    {
        $key = 'game:bp:last:'.$uid;
        Redis::set($key,$r);
        return true;
    }

    public static function setTempLastGameBp($uid,$r)
    {
        $key = 'game:bp:last:temp:'.$uid;
        Redis::set($key,$r);
        return true;
    }

    public static function delTempLastGameBp($uid)
    {
        $key = 'game:bp:last:temp:'.$uid;
        Redis::del($key);
        return true;
    }

    public static function getWeekOrMonthRecharge($uid)
    {
        $today = strtotime(date('Y-m-d'));
        $newtoday = date('Y-m-d');
        /*$keyweek = 'user:week:'.$uid;
        $keymonth = 'user:month:'.$uid;*/
        $cards = 'user:cards:'.$uid;
        $nowcards = 'daily:coin:card:'.$uid;

        /*$week = Redis::get($keyweek);
        $month = Redis::get($keymonth);
        $weeknum =  $week ? strtotime($week): 0;
        $monthnum =  $month ? strtotime($month): 0;

        if($weeknum>$monthnum){
            $c = round(($today - $weeknum) / 3600 / 24);
            if($c<=7) {
                Redis::hSet($nowcards, "week;" . $week, date("Y-m-d", $weeknum + 3600 * 24));
            }else{
                $c = static::getHavePass($uid);
                if(empty($c)) {
                    Redis::hSet($nowcards, "week;" . $week, date("Y-m-d", $weeknum + 3600 * 24));
                }
            }
        }else if($monthnum>$weeknum || $monthnum>0){
            $c = round(($today - $monthnum) / 3600 / 24);
            if($c<=30) {
                Redis::hSet($nowcards, "month;" . $month, date("Y-m-d", $monthnum + 3600 * 24));
            }else{
                $c = static::getHavePass($uid);
                if(empty($c)) {
                    Redis::hSet($nowcards, "month;" . $month, date("Y-m-d", $monthnum + 3600 * 24));
                }
            }
        }

        if($weeknum>0){
            Redis::del($keyweek);
            //Redis::hSet($cards,$week,"week");
        }
        if($monthnum>0){
            Redis::del($keymonth);
            //Redis::hSet($cards,$month,"month");
        }*/

        $nowcard = Redis::hGetAll($nowcards);
        $card = Redis::hGetAll($cards);


        if(!empty($nowcard)){
            foreach($nowcard as $item => $start){
                $s = explode(";",$item);
                $type = $s[0];
                $purcha = $s[1];
                $n = strtotime($start);
                $v = round(($today - $n) / 3600 / 24)+1;
                if($type=="week"){
                    if($v>7){
                        $endday = date("Y-m-d",$n + 3600 * 24 * 7);
                        $newtime = static::getNewCard($uid,$newtoday,$v-7,$endday,$purcha);
                        if(!empty($newtime)){
                            $forlove = explode(";",$newtime);
                            Redis::hSet($nowcards,$card[$forlove[0]].";".$forlove[0],$forlove[1]);
                            Redis::hDel($nowcards,$item);
                            Redis::hDel($cards,$forlove[0]);
                            static::delHavePass($uid);
                            return $card[$forlove[0]].":".$forlove[1];
                        }else{
                            Redis::del($nowcards);
                            return 'week:'.$start;
                        }
                    }else{
                        return 'week:'.$start;
                    }
                }else if($type=="month"){
                    if($v>30){
                        $endday = date("Y-m-d",$n + 3600 * 24 * 30);
                        $newtime = static::getNewCard($uid,$newtoday,$v-30,$endday,$purcha);
                        if(!empty($newtime)){
                            $forlove = explode(";",$newtime);
                            Redis::hSet($nowcards,$card[$forlove[0]].";".$forlove[0],$forlove[1]);
                            Redis::hDel($nowcards,$item);
                            Redis::hDel($cards,$forlove[0]);
                            static::delHavePass($uid);
                            return $card[$forlove[0]].":".$forlove[1];
                        }else{
                            Redis::del($nowcards);
                            return 'month:'.$start;
                        }
                    }else{
                        return 'month:'.$start;
                    }
                }
            }
        }else{
            $newtime = static::getNewCard($uid,$newtoday);
            if(!empty($newtime)){
                $forlove = explode(";",$newtime);
                $old = date("Y-m-d",strtotime($forlove[1]));
                $v = round(($today - strtotime($old)) / 3600 / 24);
                if($v<0){
                    return 0;
                }else{
                    Redis::hSet($nowcards,$card[$forlove[0]].";".$forlove[0],$forlove[1]);
                    Redis::hDel($cards,$forlove[0]);
                    static::delHavePass($uid);
                    return $card[$forlove[0]].":".$forlove[1];
                }
            }else{
                return 0;
            }

        }
    }

    public static function getNewCard($uid,$newtoday,$pastday=0,$startday="",$oldtime="0"){
        $today = strtotime($newtoday);
        $cards = 'user:cards:'.$uid;
        $card = Redis::hGetAll($cards);
        ksort($card);
        $uniold = strtotime($oldtime);
        if($oldtime=="0"){
            $uniold = 0;
        }
        if(!empty($startday)) {
            foreach ($card as $tims => $type) {
                $n = strtotime($tims);
                $ccc = round(($today - strtotime(date("Y-m-d",$n))) / 3600 / 24);
                if ($n > $uniold && $ccc > 0) {
                    if ($type == "week") {
                        if ($pastday > 7) {
                            Redis::hDel($cards, $tims);
                            $pastday = $pastday - 7;
                            $startday = date("Y-m-d", strtotime($startday) + 3600 * 24 * 7);
                        } else {
                            return $tims . ";" . $startday;
                        }
                    }
                    if ($type == "month") {
                        if ($pastday > 30) {
                            Redis::hDel($cards, $tims);
                            $pastday = $pastday - 30;
                            $startday = date("Y-m-d", strtotime($startday) + 3600 * 24 * 30);
                        } else {
                            return $tims . ";" . $startday;
                        }
                    }
                } else if($n > $uniold){
                    return 0;
                } else{
                    Redis::hDel($cards, $tims);
                }
            }
        }else{
            foreach ($card as $tims => $type) {
                $n = strtotime($tims);
                $ccc = round(($today - strtotime(date("Y-m-d",$n))) / 3600 / 24);
                if(empty($startday)){
                    $startday = date("Y-m-d", strtotime($tims) + 3600 * 24);
                }
                $c = round(($today - strtotime($startday)) / 3600 / 24)+1;
                if($ccc > 0) {
                    if ($type == "week") {
                        if ($c > 7) {
                            Redis::hDel($cards, $tims);
                            $startday = date("Y-m-d", strtotime($startday) + 3600 * 24 * 7);
                        } else {
                            return $tims . ";" . $startday;
                        }
                    }
                    if ($type == "month") {
                        if ($c > 30) {
                            Redis::hDel($cards, $tims);
                            $startday = date("Y-m-d", strtotime($startday) + 3600 * 24 * 30);
                        } else {
                            return $tims . ";" . $startday;
                        }
                    }
                }
            }
        }
        return 0;
    }

    public static function getDailyHaveCoin($uid)
    {
        $key = 'daily:coin:'.$uid;
        $coin = Redis::get($key);
        if (empty($coin)) {
            return "";
        }
        return $coin;
    }

    public static function setDailyHaveCoin($uid,$coin)
    {
        $key = 'daily:coin:'.$uid;
        $t = time();
        $end = mktime(23,59,59,date("m",$t),date("d",$t),date("Y",$t));
        $ttl =$end-$t;
        $bp = Redis::setex($key,$ttl,$coin);
        if (empty($bp)) {
            return "";
        }
        return "1";
    }

    public static function getHavePass($uid)
    {
        $key = 'daily:coin:pass:'.$uid;
        $coin = Redis::get($key);
        if (empty($coin)) {
            return "";
        }
        return $coin;
    }

    public static function setHavePass($uid)
    {
        $key = 'daily:coin:pass:'.$uid;
        Redis::set($key,1);
        return true;
    }

    public static function delHavePass($uid)
    {
        $key = 'daily:coin:pass:'.$uid;
        Redis::del($key);
        return true;
    }

    public static function getBpSumMax()
    {
        $key = 'bp:accumulation:max';
        return Redis::get($key);
    }

    public static function getDailyCheckIn($uid)
    {
        $key = 'checkin:daily:'.$uid;
        $check = Redis::get($key);
        if (empty($check)) {
            return "";
        }
        return $check;
    }

    public static function setDailyCheckIn($uid)
    {
        $key = 'checkin:daily:'.$uid;
        $t = time();
        $end = mktime(23,59,59,date("m",$t),date("d",$t),date("Y",$t));
        $ttl =$end-$t;
        $ci = Redis::setex($key,$ttl,"1");
        if (empty($ci)) {
            return "";
        }
        return "1";
    }

    public static function getDailyCheckInNum($uid)
    {
        $key = 'checkin:oldcount:'.$uid;
        $check = Redis::hgetall($key);
        if (empty($check)) {
            return "";
        }
        return $check;
    }

    public static function setDailyCheckInNum($uid,$day,$n,$data)
    {
        $n = $n ?: 0;
        $key = 'checkin:oldcount:'.$uid;
        Redis::hset($key,"day",$day);
        Redis::hset($key,"count",$n);
        Redis::hset($key,"data",$data);
        return true;
    }

    public static function getDailyCheckInMonthNum($uid)
    {
        $key = 'checkin:newcount:'.$uid;
        $check = Redis::hGetall($key);
        if (empty($check)) {
            return "";
        }
        return $check;
    }

    public static function setDailyCheckInMonthNum($uid,$day,$n,$data,$num)
    {
        $n = $n ?: 0;
        $key = 'checkin:newcount:'.$uid;
        Redis::hset($key,"day",$day);
        Redis::hset($key,"count",$n);
        Redis::hset($key,"data",$data);
        Redis::hset($key,"num",$num);
        return true;
    }

    public static function getUserInviteBannerCounts($uid)
    {
        $key = 'invite:banner:counts:'.$uid;
        $check = Redis::hGetAll($key);
        if (empty($check)) {
            return "";
        }
        return $check;
    }

    public static function setUserInviteBannerCounts($uid,$day,$data)
    {
        $key = 'invite:banner:counts:'.$uid;
        $check = static::getUserInviteBannerCounts($uid);
        $count = 1;
        if(!empty($check)){
            $day = $check["day"].",".$day;
            $count = $check["count"] + 1;
            $data = $check["data"].",".$data;
        }
        Redis::hset($key,"day",$day);
        Redis::hset($key,"count",$count);
        Redis::hset($key,"data",$data);

        return true;
    }

    public static function getDailyInviteBanner($uid)
    {
        $key = 'invite:banner:daily:'.$uid;
        $banner = Redis::get($key);
        if (empty($banner)) {
            return "";
        }
        return $banner;
    }

    public static function setDailyInviteBanner($uid)
    {
        $key = 'invite:banner:daily:'.$uid;
        $t = time();
        $end = mktime(23,59,59,date("m",$t),date("d",$t),date("Y",$t));
        $ttl =$end-$t;
        $banner = Redis::setex($key,$ttl,"1");
        if (empty($banner)) {
            return "";
        }
        return "1";
    }

    public static function getBkbRoomScore($room_id)
    {
        $key = 'history:score:'.$room_id;
        $score = Redis::hGet($key,"score");
        if (empty($score)) {
            return 0;
        }
        return $score;
    }

    public static function setBkbRoomScore($room_id,$score,$userId)
    {
        $key = 'history:score:'.$room_id;
        $score = Redis::hSet($key,"score",$score);
        $userId = Redis::hSet($key,"userId",$userId);
        if (empty($score) || empty($userId)) {
            return 0;
        }
        return 1;
    }

    public static  function getCashFee(){
        $display = json_decode(static::getAppKey("shipping_cash"),true);
        $clientType = Request::getHeader('X_WAWAJI_CLIENT_PLATFORM');
        if(array_key_exists("cash",$display) && $display["cash"]>0 && array_key_exists("platform",$display) && strpos($display["platform"],";".$clientType.";")!==false){
            return 1;
        }else{
            return 0;
        }
    }

}
